package com.boarsoft.rpc.bean;

import java.io.Serializable;
import java.util.List;

import org.dom4j.Node;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.boarsoft.common.util.StringUtil;
import com.boarsoft.rpc.util.XmlConfigUtil;

public class RpcReferenceConfig extends RpcFaceConfig implements Serializable {
	private static final long serialVersionUID = -238430885029993755L;
	private static final Logger log = LoggerFactory.getLogger(RpcReferenceConfig.class);

	/** 决定是否走HTTP调用，同一接口要么都走HTTP，要么都走RPC */
	protected String uri;
	/** 指定服务提供者实例地址 */
	protected String direct;
	/** 泛化调用 */
	protected boolean generalized;

	public RpcReferenceConfig() {
		// 仅为Kryo序列化保留
	}

	public RpcReferenceConfig(String group, String name, String interfaceName, String version, String id)
			throws ClassNotFoundException {
		super(group, name, interfaceName, version, id);
	}

	@SuppressWarnings("unchecked")
	public RpcReferenceConfig(Node rn) throws Exception {
		super(rn);
		// 父类有设置timeout，这里就不用了
		// this.timeout = XmlConfigUtil.getIntegerAttr(rn, "@timeout",
		// this.timeout);
		if (StringUtil.isEmpty(this.id)) {
			throw new RuntimeException("Reference.id can not be blank.");
		}
		this.uri = XmlConfigUtil.getStringAttr(rn, "@uri", null);
		this.direct = XmlConfigUtil.getStringAttr(rn, "@direct", null);

		List<Node> ml = rn.selectNodes("method");
		for (Node m : ml) {
			String name = XmlConfigUtil.getStringAttr(m, "@name", null);
			String ms = this.getMethodSign(m, name);
			RpcMethodConfig mc = this.methodConfigMap.get(ms);
			if (mc == null) {
				throw new IllegalStateException(String.format("Method %s/%s does not exists", sign, ms));
			}
			mc.setType(XmlConfigUtil.getStringAttr(m, "@type", this.type));
			mc.setTimeout(XmlConfigUtil.getIntegerAttr(m, "@timeout", this.timeout));
			mc.setCallback(XmlConfigUtil.getStringAttr(m, "@callback", null));
			mc.setAutoMock(XmlConfigUtil.getBooleanAttr(m, "@autoMock", false));
		}
	}

	@Override
	public Class<?> getInterfaceClazz() {
		if (!generalized && interfaceClazz == null) {
			synchronized (this) {
				if (interfaceClazz == null) {
					try {
						interfaceClazz = Class.forName(interfaceName);
					} catch (ClassNotFoundException e) {
						log.warn("Generalized interface {}", interfaceName);
						generalized = true;
					}
				}
			}
		}
		return interfaceClazz;
	}

	public String getUri() {
		return uri;
	}

	public void setUri(String uri) {
		this.uri = uri;
	}

	public String getDirect() {
		return direct;
	}

	public void setDirect(String direct) {
		this.direct = direct;
	}

	public boolean isGeneralized() {
		return generalized;
	}

	public void setGeneralized(boolean generalized) {
		this.generalized = generalized;
	}

}